﻿using LiteDb;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using DidaManagerOnline.Native.RemoteTransmission;
using NetCoreServer;
using System.Net;
using DidaManager.Log;
using WebSocketSharp;
using System.Text.RegularExpressions;
using DidaManager.Native.Network;

namespace DidaManager.Native.RemoteTransmission
{
    public class RemoteTransManager
    {
        private TransSerialPortHandler? m_serialPortHandler = null;
        private TransTcpServer? m_tcpServer = null;
        private TransWebSocketClient? m_webSocketClient = null;
        public DirectData m_directData = new DirectData();
        public bool bInterceptAT = false;
        private DidaManager.Native.SerialPort.SerialPortManager m_serialPortManager;


        public RemoteTransManager(DidaManager.Native.SerialPort.SerialPortManager serialPortManager)
        {
            m_serialPortManager = serialPortManager;
            m_serialPortHandler = new TransSerialPortHandler();
            m_serialPortHandler.DataReceived += this.SerialPort_MessageReceived;
        }

        private string GetSerialPort(string portName)
        {
            if (m_serialPortManager == null)
            {
                return string.Empty;
            }
            var port = m_serialPortManager.GetSerialPort(portName);
            return port;
        }

        public int GetCOMPortNumber(string port)
        {
            // 使用正则表达式匹配 COM 后面的数字
            Match match = Regex.Match(port, @"\d+");

            if (match.Success)
            {
                // 将匹配到的数字转换为整数并返回
                return int.Parse(match.Value);
            }

            return -1; // 如果未找到数字，返回 -1 表示未成功提取
        }

        public object GetProductList(object param)
        {
            try
            {
                List<string> list = new List<string>();
                TransHttpManager.Instance.GetProductList(ref list);
                // 将list转换为json
                string json = JsonConvert.SerializeObject(list);
                return ApiResponse.Success(json);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail("获取产品列表失败" + ex.Message);
            }
        }
        
        public object GetDevicesList(object param)
        {
            try
            {
                if (param == null)
                {
                    return ApiResponse.Fail("获取设备列表失败,参数不能为空");
                }
                string product = param.ToString() ?? string.Empty;
                if (string.IsNullOrEmpty(product))
                {
                    return ApiResponse.Fail("获取设备列表失败,产品不能为空");
                }
                List<string> list = new List<string>();
                TransHttpManager.Instance.GetDeviceList(ref list, product);
                // 将list转换为json
                string json = JsonConvert.SerializeObject(list);
                return ApiResponse.Success(json);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail("获取设备列表失败" + ex.Message);
            }
        }

        public object GetTransPortList(object param)
        {
            try
            {
                if (param == null)
                {
                    return ApiResponse.Fail("获取透传端口列表失败,参数不能为空");
                }
                string product = param.ToString() ?? string.Empty;
                if (string.IsNullOrEmpty(product))
                {
                    return ApiResponse.Fail("获取透传端口列表失败,产品不能为空");
                }
                List<string> list = new List<string>();
                TransHttpManager.Instance.GetTransPortList(ref list, product);
                // 将list转换为json
                string json = JsonConvert.SerializeObject(list);
                return ApiResponse.Success(json);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail("获取透传端口列表失败" + ex.Message);
            }
        }

        public object GetDeviceDetailList(object param)
        {
            try
            {
                if (param == null)
                {
                    return ApiResponse.Fail("获取设备详情列表失败,参数不能为空");
                }
                List<NSDevice.MyDevice> list = new List<NSDevice.MyDevice>();
                string product = param.ToString() ?? string.Empty;
                TransHttpManager.Instance.GetDeviceDetailList(ref list, product);
                // 将list转换为json ，list中的数据为NSDevice.MyDevice
                string json = JsonConvert.SerializeObject(list);
                return ApiResponse.Success(json);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail("获取设备详情列表失败" + ex.Message);
            }
        }

        public object ConnectSerial(object param)
        {
            try
            {
                if (m_serialPortHandler == null)
                {
                    return ApiResponse.Fail("串口处理器未初始化");
                }

                if (m_serialPortHandler.IsOpen())
                {
                    m_serialPortHandler.Close();
                    return ApiResponse.Success("串口已关闭");
                }      
                          
                if (param == null)
                {
                    return ApiResponse.Fail("连接串口失败,参数不能为空");
                }
                string portInfo = param.ToString() ?? string.Empty;
                if (string.IsNullOrEmpty(portInfo))
                {
                    return ApiResponse.Fail("连接串口失败,设备不能为空");
                }
                // 解析json字符串
                var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(portInfo);
                string port = json?["port"] ?? string.Empty;
                string baud = json?["baud"] ?? string.Empty;
                string data = json?["data"] ?? string.Empty;
                string parity = json?["parity"] ?? string.Empty;
                string stop = json?["stop"] ?? string.Empty;
                string target = json?["target"] ?? string.Empty;

                string name = GetSerialPort(port);

                m_directData.PortType = "serial";
                m_directData.SerialParams = baud + parity.Substring(0, 1) + data + stop;
                m_directData.SerialPort = target;
                m_directData.SerialPortNum = GetCOMPortNumber(target);

                // 连接串口
                m_serialPortHandler.Initialize(name, baud, data, stop, parity);
                bool bRet = m_serialPortHandler.Open();
                if (!bRet)
                {
                    return ApiResponse.Fail("连接串口失败");
                }
                return ApiResponse.Success("连接串口成功");
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail("连接串口失败" + ex.Message);
            }
        }

        public object Start(object param)
        {
            string remoteTransAddress = NetworkConfig.Instance.GetRemoteTransAddress();
            int remoteTransPort = int.Parse(NetworkConfig.Instance.GetRemoteTransPort());

            if (string.IsNullOrEmpty(remoteTransAddress) || remoteTransPort == 0)
            {
                return ApiResponse.Fail("开始远程透传失败,地址或端口不能为空");
            }

            // 需要从param获取产品和设备名称
            if (param == null)
            {
                return ApiResponse.Fail("开始远程透传失败,参数不能为空");
            }
            // param是json字符串，需要解析
            var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(param?.ToString() ?? string.Empty);
            // string product = json?["product"] ?? string.Empty;
            string device = json?["device"] ?? string.Empty;
            if (string.IsNullOrEmpty(device))
            {
                return ApiResponse.Fail("开始远程透传失败,设备不能为空");
            }
            string clientId = TransHttpManager.Instance.GetDeviceClientId(device);
            NetworkConfig.Instance.SetRemoteTransClientId(clientId);

            bool bRet = RunWebSocket(remoteTransAddress, remoteTransPort);
            if (!bRet)
            {
                return ApiResponse.Fail("开始远程透传失败");
            }
            return ApiResponse.Success("开始远程透传成功");
        }

        public object Listen(object param)
        {
            if (param == null)
            {
                return ApiResponse.Fail("监听失败,参数不能为空");
            }
            string portInfo = param.ToString() ?? string.Empty;
            if (string.IsNullOrEmpty(portInfo))
            {
                return ApiResponse.Fail("监听失败,端口不能为空");
            }
            // 解析json字符串
            var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(portInfo);
            string address = json?["netAddress"] ?? string.Empty;
            string port = json?["netPort"] ?? string.Empty;
            string plcAddress = json?["plcAddress"] ?? string.Empty;
            string plcPort = json?["plcPort"] ?? string.Empty;
            if (string.IsNullOrEmpty(address) || string.IsNullOrEmpty(port))
            {
                return ApiResponse.Fail("监听失败,地址或端口不能为空");
            }

            m_directData.PortType = "net";
            m_directData.Ip = plcAddress;
            m_directData.NetPort = 0;
            if (plcPort.Length != 0)
            {
                m_directData.NetPort = int.Parse(plcPort);
            }

            bool bRet = ListenTcpServer(address, port);
            if (!bRet)
            {
                return ApiResponse.Fail("监听失败");
            }
            return ApiResponse.Success("监听成功");
        }

        public object GetTargetPort(object param)
        {
            return ApiResponse.Success("获取目标端口成功");
        }

        public object PortTypeSel(object param)
        {
            return ApiResponse.Success("选择端口类型成功");
        }

#region 数据处理
       public bool ListenTcpServer(string address, string port)
        {
            int result = int.Parse(port);
            bool bRet = false;

            if (!IPAddress.TryParse(address, out _))
            {
                throw new ArgumentException("Invalid IP address.");
            }

            try
            {
                // 尝试连接的代码
                if (m_tcpServer == null)
                {
                    m_tcpServer = new TransTcpServer(address, result);
                    m_tcpServer.DataReceived += this.TcpServer_MessageReceived;
                    m_tcpServer.ConnectStatus += this.TcpServer_ConnectStatusReceived;
                }

                // 判断是否已经打开
                if (!m_tcpServer.IsStarted)
                {
                    bRet = m_tcpServer.Start();
                }
                else
                {
                    bRet = m_tcpServer.Stop();
                    m_tcpServer = null;
                }
            }
            catch (Exception ex)
            {
                // 处理连接失败的异常
                LogManager.Error("TCP Server Connection failed: " + ex.Message);
            }
            return bRet;
        }

        public void TcpServer_MessageReceived(byte[] buffer, long offset, long size)
        {
            string message = BitConverter.ToString(buffer, (int)offset, (int)size);
            LogManager.Debug("TcpServer Received message in MessageReceiver: " + message);
            if (m_webSocketClient != null)
            {
                DirectData temp = new DirectData();
                temp.Data = Convert.ToBase64String(buffer, (int)offset, (int)size); 
                temp.Id = ReqTransWebsocketData.GenerateClientId();
                temp.PortType = m_directData.PortType;
                temp.SerialParams = m_directData.SerialParams;
                temp.SerialPort = m_directData.SerialPort;
                temp.SerialPortNum = m_directData.SerialPortNum;
                temp.Ip = m_directData.Ip;
                temp.NetPort = m_directData.NetPort;
                temp.Function = "data";
                temp.DataLen = (int)size;

                m_webSocketClient.SendMessage(temp.ToJson());
            }
        }

        private void TcpServer_ConnectStatusReceived(string data)
        {
            LogManager.Debug("Tcp connect message in ConnectStatus: " + data);
            if (m_webSocketClient != null)
            {
                DirectData temp = new DirectData();
                temp.Data = "";
                temp.Id = ReqTransWebsocketData.GenerateClientId();
                temp.PortType = m_directData.PortType;
                temp.SerialParams = m_directData.SerialParams;
                temp.SerialPort = m_directData.SerialPort;
                temp.SerialPortNum = m_directData.SerialPortNum;
                temp.Ip = m_directData.Ip;
                temp.NetPort = m_directData.NetPort;
                temp.Function = data;

                m_webSocketClient.SendMessage(temp.ToJson());
            }
        }

        public bool RunWebSocket(string address, int port)
        {
            string url = TransWebSocketClient.GetWebSocketPath(address, port);

            try
            {
                if (m_webSocketClient == null)
                {
                    m_webSocketClient = new TransWebSocketClient(url, ReqTransWebsocketData.GenerateClientId());
                    m_webSocketClient.MessageReceived += this.WebSocketClient_MessageReceived!;
                    m_webSocketClient.ConnectStatus += this.WebSocketClient_ConnectStatus;
                }

                if (m_webSocketClient.IsConnected())
                {
                    WebSocketClient_ConnectStatus("stop");
                    Task.Delay(300).ContinueWith(_ => // 延时300毫秒确保断开数据有发送后，再关闭websocket
                    {
                        m_webSocketClient.Close();
                    });
                }
                else
                {
                    m_webSocketClient.Connect();
                    if (!m_webSocketClient.IsConnected())
                    {
                        return false;
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理连接失败的异常
                LogManager.Error("WebSocket Connection failed: " + ex.Message);
                return false;
            }

            return true;
        }

        public void WebSocketClient_MessageReceived(object sender, MessageEventArgs e)
        {
            LogManager.Debug("Websocket Received message in MessageReceiver: " + e.Data);
            if (m_tcpServer != null)
            {
                m_tcpServer.SendData(e.Data);
            }
            if (m_serialPortHandler != null)
            {
                m_serialPortHandler.Write(e.Data);
            }
        }

        public void WebSocketClient_ConnectStatus(string data)
        {
            LogManager.Debug("Websocket connect status: " + data);
            if (m_webSocketClient != null)
            {
                DirectData temp = new DirectData();
                temp.Data = "";
                temp.Id = ReqTransWebsocketData.GenerateClientId();
                temp.PortType = m_directData.PortType;
                temp.SerialParams = m_directData.SerialParams;
                temp.SerialPort = m_directData.SerialPort;
                temp.SerialPortNum = m_directData.SerialPortNum;
                temp.Ip = m_directData.Ip;
                temp.NetPort = m_directData.NetPort;
                temp.Function = data;

                m_webSocketClient.SendMessage(temp.ToJson());
            }
        }

        public void SerialPort_MessageReceived(byte[] buffer, int offset, int count)
        {
            string message = BitConverter.ToString(buffer, (int)offset, (int)count);
            LogManager.Debug("SerialPort_MessageReceived Received message in MessageReceiver: " + message);
            // 需要开始拦截at指令
            if(bInterceptAT)
            {
                string str = System.Text.Encoding.UTF8.GetString(buffer,offset,count);
                if (str.StartsWith("ATD"))
                {
                    if (m_serialPortHandler != null)
                    {
                        m_serialPortHandler.WriteRaw("CONNECT");
                    }
                    return;
                }
                if (str.StartsWith("AT"))
                {
                    if (m_serialPortHandler != null)
                    {
                        m_serialPortHandler.WriteRaw("OK");
                    }
                    return;
                }
            }

            if (m_webSocketClient != null)
            {
                DirectData temp = new DirectData();
                temp.Data = Convert.ToBase64String(buffer, (int)offset, (int)count);
                temp.Id = ReqTransWebsocketData.GenerateClientId();
                temp.PortType = m_directData.PortType;
                temp.SerialParams = m_directData.SerialParams;
                temp.SerialPort = m_directData.SerialPort;
                temp.SerialPortNum = m_directData.SerialPortNum;
                temp.Ip = m_directData.Ip;
                temp.NetPort = m_directData.NetPort;
                temp.Function = "data";
                temp.DataLen = count;

                m_webSocketClient.SendMessage(temp.ToJson());
            }
        }
       
#endregion

    }
}
